import { extend, isFn, options, clearArray, noop } from "./util";
import { CurrentOwner } from "./createElement";

/**
 *组件的基类
 *
 * @param {any} props
 * @param {any} context
 */
var mountOrder = 1;
export function Component(props, context) {
  //防止用户在构造器生成JSX
  CurrentOwner.cur = this;
  this.__mountOrder = mountOrder++;
  this.context = context;
  this.props = props;
  this.refs = {};
  this.state = null;
  this.__pendingCallbacks = [];
  this.__pendingStates = [];
  this.__current = noop;
  /*
    * this.__hydrating = true 表示组件正在根据虚拟DOM合成真实DOM
    * this.__renderInNextCycle = true 表示组件需要在下一周期重新渲染
    * this.__forceUpdate = true 表示会无视shouldComponentUpdate的结果
    */
}

Component.prototype = {
  constructor: Component,//必须重写constructor,防止别人在子类中使用Object.getPrototypeOf时找不到正确的基类
  replaceState() {
        console.warn("此方法末实现"); // eslint-disable-line
  },

  setState(state, cb) {
    debounceSetState(this, state, cb);
  },
  isMounted() {
    return !!this.__dom;
  },
  forceUpdate(cb) {
    debounceSetState(this, true, cb);
  },
  __mergeStates: function (props, context) {
    var n = this.__pendingStates.length;
    if (n === 0) {
      return this.state;
    }
    var states = clearArray(this.__pendingStates);
    var nextState = extend({}, this.state);
    for (var i = 0; i < n; i++) {
      var partial = states[i];
      extend(nextState, isFn(partial)
        ? partial.call(this, nextState, props, context)
        : partial);
    }
    return nextState;
  },

  render() { }
};

function debounceSetState(a, b, c) {
  if (a.__didUpdate) {//如果用户在componentDidUpdate中使用setState，要防止其卡死
    setTimeout(function () {
      a.__didUpdate = false;
      setStateImpl.call(a, b, c);
    }, 300);
    return;
  }
  setStateImpl.call(a, b, c);
}
function setStateImpl(state, cb) {
  if (isFn(cb)) {
    this
      .__pendingCallbacks
      .push(cb);
  }
  let hasDOM = this.__dom;
  if (state === true) {//forceUpdate
    this.__forceUpdate = true;
  } else {//setState
    this
      .__pendingStates
      .push(state);
  }
  if (!hasDOM) { //组件挂载期
    //componentWillUpdate中的setState/forceUpdate应该被忽略 
    if (this.__hydrating) {
      //在挂载过程中，子组件在componentWillReceiveProps里调用父组件的setState，延迟到下一周期更新
      this.__renderInNextCycle = true;
    }

  } else { //组件更新期
    if (this.__receiving) {
      //componentWillReceiveProps中的setState/forceUpdate应该被忽略 
      return;
    }
    this.__renderInNextCycle = true;
    if (options.async) {
      //在事件句柄中执行setState会进行合并
      options.enqueueUpdate(this);
      return;
    }
    if (this.__hydrating) {
      // 在componentDidMount里调用自己的setState，延迟到下一周期更新
      // 在更新过程中， 子组件在componentWillReceiveProps里调用父组件的setState，延迟到下一周期更新
      return;
    }
    //  不在生命周期钩子内执行setState
    options.flushBatchedUpdates([this]);
  }
}
